package org.sag.mutation;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.sag.coverage.PolicyCoverageFactory;
import org.sag.coverage.PolicySpreadSheetTestRecord;
import org.sag.coverage.PolicySpreadSheetTestSuite;
import org.sag.faultlocalization.SpectrumBasedDiagnosisResults;
import org.sag.faultlocalization.SpectrumBasedFaultLocalizer;

public class PolicyMutant {
	private String number;
	private String mutantFilePath;
	// change to the following if multiple faults need to be considered
	// int[] faultLocations 
	private int faultLocation;
	
	public PolicyMutant(String number, String fileName, int bugPosition){
		this.number = number;
		this.mutantFilePath = fileName;
		this.faultLocation = bugPosition;
	}
	
	public ArrayList<SpectrumBasedDiagnosisResults> run(ArrayList<PolicySpreadSheetTestRecord> testCases) throws Exception{
		PolicyCoverageFactory.init();
		new PolicySpreadSheetTestSuite(testCases, mutantFilePath).runAllTests();
		return SpectrumBasedFaultLocalizer.applyAllFaultLocalizersToPolicyMutant(faultLocation);
	}

	public String getNumber(){
		return number;
	}

	public String getMutantFilePath(){
		return mutantFilePath;
	}
	
	public int getFaultLocation(){
		return faultLocation;
	}
	
	public static final String MUTANT_KEYWORD = "MUTANT";

	public static ArrayList<PolicyMutant> readPolicyMutantsSpreadSheet(String policyMutantSpreadsheetFile){
		ArrayList<PolicyMutant> policyMutants = new ArrayList<PolicyMutant>();
		try {
			FileInputStream inputStream = new FileInputStream(policyMutantSpreadsheetFile);				
			HSSFWorkbook workBook = new HSSFWorkbook (inputStream);
			Sheet sheet = workBook.getSheetAt(0);
			for (Row row: sheet){
				loadMutantRow(policyMutants, row);
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return policyMutants;
	}
	
	private static void loadMutantRow(ArrayList<PolicyMutant> testSuite, Row row){
		if (row.getCell(0)==null || row.getCell(1)==null)
			return;
		String keyword = row.getCell(0).toString().trim();
		if (keyword.equals("") || keyword.startsWith("//") || !keyword.substring(0,MUTANT_KEYWORD.length()).equalsIgnoreCase(MUTANT_KEYWORD))
			return;
		String policyMutantFile = row.getCell(1)!=null? row.getCell(1).toString(): "";
		String bugPositionString = row.getCell(2)!=null? row.getCell(2).toString(): "";
		int bugPosition = -1;
		try {
			bugPosition = (int) Double.parseDouble(bugPositionString);
		}
		catch (Exception e) {
			bugPosition = -1;
		}		
		if (!policyMutantFile.equals("")) {
			testSuite.add(new PolicyMutant(keyword, policyMutantFile, bugPosition));
		}
	}

	public static void writePolicyMutantsSpreadSheet(ArrayList<PolicyMutant> mutantList, String mutantSpreadSheetFileName){
		HSSFWorkbook workBook = new HSSFWorkbook();
		workBook.createSheet("mutation list");
		Sheet sheet = workBook.getSheetAt(0);
		Row row = sheet.createRow(0);
		for (int mutantIndex =0; mutantIndex<mutantList.size(); mutantIndex++){
			row = sheet.createRow(mutantIndex+1);
			writeMutantRow(row, mutantList.get(mutantIndex)); 
		}
		try {
			FileOutputStream out = new FileOutputStream(mutantSpreadSheetFileName);
			workBook.write(out);
			out.close();
		}
		catch (IOException ioe){
			ioe.printStackTrace();
		}
	}

	private static void writeMutantRow(Row row, PolicyMutant mutant){
		Cell idCell = row.createCell(0);
		idCell.setCellValue(mutant.getNumber());
		Cell pathCell = row.createCell(1);
		pathCell.setCellValue(mutant.getMutantFilePath());
		Cell faultLocationCell = row.createCell(2);
		faultLocationCell.setCellValue(mutant.getFaultLocation());
	}

}
